package com.ebt.m.customer.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;

import com.ebt.m.R;
import com.ebt.m.data.entity.Customer;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class BitmapUtil {

    private BitmapUtil() {
    }

    /**
     * Returns Width or Height of the picture, depending on which size is smaller. Doesn't actually
     * decode the picture, so it is pretty efficient to run.
     */
    public static int getSmallerExtentFromBytes(byte[] bytes) {
        final BitmapFactory.Options options = new BitmapFactory.Options();

        // don't actually decode the picture, just return its bounds
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);

        // test what the best sample size is
        return Math.min(options.outWidth, options.outHeight);
    }

    /**
     * Finds the optimal sampleSize for loading the picture
     *
     * @param originalSmallerExtent Width or height of the picture, whichever is smaller
     * @param targetExtent          Width or height of the target view, whichever is bigger.
     *                              <p>
     *                              If either one of the parameters is 0 or smaller, no sampling is applied
     */
    public static int findOptimalSampleSize(int originalSmallerExtent, int targetExtent) {
        // If we don't know sizes, we can't do sampling.
        if (targetExtent < 1) return 1;
        if (originalSmallerExtent < 1) return 1;

        // Test what the best sample size is. To do that, we find the sample size that gives us
        // the best trade-off between resulting image size and memory requirement. We allow
        // the down-sampled image to be 20% smaller than the target size. That way we can get around
        // unfortunate cases where e.g. a 720 picture is requested for 362 and not down-sampled at
        // all. Why 20%? Why not. Prove me wrong.
        int extent = originalSmallerExtent;
        int sampleSize = 1;
        while ((extent >> 1) >= targetExtent * 0.8f) {
            sampleSize <<= 1;
            extent >>= 1;
        }

        return sampleSize;
    }

    /**
     * Decodes the bitmap with the given sample size
     */
    public static Bitmap decodeBitmapFromBytes(byte[] bytes, int sampleSize) {
        final BitmapFactory.Options options;
        if (sampleSize <= 1) {
            options = null;
        } else {
            options = new BitmapFactory.Options();
            options.inSampleSize = sampleSize;
        }
        return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
    }

    public static Bitmap toRoundBitmap(Bitmap bitmap) {
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        float roundPx;
        float left, top, right, bottom, dst_left, dst_top, dst_right, dst_bottom;
        if (width <= height) {
            roundPx = width / 2;
            top = 0;
            bottom = width;
            left = 0;
            right = width;
            height = width;
            dst_left = 0;
            dst_top = 0;
            dst_right = width;
            dst_bottom = width;
        } else {
            roundPx = height / 2;
            float clip = (width - height) / 2;
            left = clip;
            right = width - clip;
            top = 0;
            bottom = height;
            width = height;
            dst_left = 0;
            dst_top = 0;
            dst_right = height;
            dst_bottom = height;
        }

        Bitmap output = Bitmap.createBitmap(width,
                height, Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect src = new Rect((int) left, (int) top, (int) right, (int) bottom);
        final Rect dst = new Rect((int) dst_left, (int) dst_top, (int) dst_right, (int) dst_bottom);
        final RectF rectF = new RectF(dst);

        paint.setAntiAlias(true);

        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, src, dst, paint);
        return output;
    }

    public static Bitmap drawableToBitmap(Drawable drawable, int width, int height) {

        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        drawable.setBounds(0, 0, width, height);
        drawable.draw(canvas);
        return bitmap;
    }


    public static Bitmap getAvatarBitmap(Context context, Customer customer, int width, int height) {
        if (customer == null) {
            Drawable drawable = context.getResources().getDrawable(R.drawable.ic_avatar);
            return BitmapUtil.drawableToBitmap(drawable, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        }
        Bitmap retBitmap = null;
        if (TextUtils.isEmpty(customer.getPortraitPath())) {
            retBitmap = getAvatarCharBitmap(context, customer, width, height);
        } else {
            retBitmap = BitmapFactory.decodeFile(customer.getPortraitPath());

            if (retBitmap == null) {
                retBitmap = getAvatarCharBitmap(context, customer, width, height);
            } else {
                retBitmap = BitmapUtil.toRoundBitmap(retBitmap);
            }
        }
        return retBitmap;
    }

    public static Bitmap getAvatarCharBitmap(Context context, Customer customer, int width, int height) {
        LetterTileDrawable.DefaultImageRequest defaultImageRequest = new LetterTileDrawable.DefaultImageRequest(customer.getName(), customer.getUuid());//charSeed colorSeed
        Drawable retDrawable = LetterTileDrawable.getDefaultImageForContact(context, defaultImageRequest);
        return BitmapUtil.drawableToBitmap(retDrawable, width, height);
    }

    public static Bitmap getAvatarCharBitmap(Context context, String nameSeed, String colorSeed, int width, int height) {
        LetterTileDrawable.DefaultImageRequest defaultImageRequest = new LetterTileDrawable.DefaultImageRequest(nameSeed, colorSeed);//charSeed colorSeed
        Drawable retDrawable = LetterTileDrawable.getDefaultImageForContact(context, defaultImageRequest);
        return BitmapUtil.drawableToBitmap(retDrawable, width, height);
    }

    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        if (reqHeight == 0 || reqWidth == 0) {
            return 1;
        }
        int inSampleSize = 1;
        int width = options.outWidth;
        int height = options.outHeight;

        if (width > reqWidth || height > reqHeight) {
            int halfWidth = width / 2;
            int halfHeight = height / 2;
            while ((halfHeight / inSampleSize) >= reqHeight
                    && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }

    public static Bitmap getSampleBitmap(String path, int width, int height) {
        FileDescriptor fileDescriptor = getFileDescriptor(path);
        if (fileDescriptor == null) {
            return null;
        }
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inJustDecodeBounds = true;
        BitmapFactory.decodeFileDescriptor(fileDescriptor, null, opt);
        opt.inSampleSize = calculateInSampleSize(opt, width, height);
        opt.inJustDecodeBounds = false;
        return BitmapFactory.decodeFileDescriptor(fileDescriptor, null, opt);
    }

    private static FileDescriptor getFileDescriptor(String path) {
        if (TextUtils.isEmpty(path)) {
            return null;
        }
        try {
            File file = new File(path);
            FileInputStream fis = new FileInputStream(file);
            return fis.getFD();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}


